﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using Dsl.Ped.Desktop.Commands;
using Dsl.Ped.Desktop.Modules;
using Dsl.Ped.Framework.AddIns;
using GalaSoft.MvvmLight.Messaging;
using System.Linq;

namespace Dsl.Ped.Desktop {
    /// <summary>
    /// Resources available for the whole desktop application
    /// </summary>
    public class ApplicationResources {
        
        /// <summary>
        /// Singleton instance within the <see cref="ApplicationResources"/>
        /// </summary>
        private static readonly ApplicationResources instance = new ApplicationResources();

        /// <summary>
        /// Messenger for the communication within the desktop editor
        /// </summary>
        private Messenger messenger = new Messenger();

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationResources"/> class.
        /// </summary>
        public ApplicationResources()
        {
            this.RegisteredModules = new List<IModule>();
            this.RegisteredApplicationCommand = new List<IApplicationCommand>();
        }

        /// <summary>
        /// Singleton instance of the <see cref="ApplicationResources"/> class
        /// </summary>
        public static ApplicationResources Instance {
            get 
            {
                return instance;
            }
        }

        /// <summary>
        /// Gets all addIns which should be included into DSLPed desktop application
        /// </summary>
        public IEnumerable<Lazy<IDslPedAddIn, IDslPedAddInMetadata>> AvalableAddIns {
            get { return availableAddIns; }
        }

        /// <summary>
        /// Gets or sets available add ins
        /// </summary>
        [ImportMany(typeof(IDslPedAddIn))]
        public IEnumerable<Lazy<IDslPedAddIn, IDslPedAddInMetadata>> availableAddIns { get; set; }

        /// <summary>
        /// Composition container used for MEF composition
        /// </summary>
        public CompositionContainer Container { get; set; }

        /// <summary>
        /// Modules registered to be injected in to DSLPed desktop application
        /// </summary>
        public List<IModule> RegisteredModules { get; private set; }

        /// <summary>
        /// Gets or sets <see cref="IApplicationCommand"/> instnaces registered in the DSLPed desktop
        /// applicatoin
        /// </summary>
        public List<IApplicationCommand> RegisteredApplicationCommand { get; private set; }

        public void RegisterModule(IModule module)
        {
            if (RegisteredModules.Contains(module))
            {
                throw new Exception("Attempt to register the same module twice");
            }
            if (CheckModuleNameRegistered(module.Name))
            {
                throw new Exception("A module of the name " + module.Name + " has already been registered");
            }

            RegisteredModules.Add(module);
        }

        /// <summary>
        /// Messenger used for the communication with the application
        /// </summary>
        public Messenger Messenger
        {
            get
            {
                return messenger;
            }
        }

        /// <summary>
        /// Directory where DSLPed application addIns are stored
        /// </summary>
        public string AddInsDirectory
        {
            get
            {
                return "./AddIns";
            }
        }

        /// <summary>
        /// Check if the module of a given name is registered
        /// </summary>
        /// <param name="moduleName">Name of the module</param>
        /// <returns>True if the module of a given name is registered</returns>
        private bool CheckModuleNameRegistered(string moduleName)
        {
            if (RegisteredModules.Select(x => x).Where(y => y.Name == moduleName).ToList().Count != 0)
            {
                return true;
            }
            return false;
        }
    }
}
